/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.leadiv.ai.minesweeper.util;

import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Vector;

/**
 *
 * @author pborrego
 */
public class C2DMatrix {
    // Inner class for S2DMatrix
    // Keeps the logic for the acutal Matrix point separate.
    class S2DMatrix {
        double _11, _12, _13;
        double _21, _22, _23;
        double _31, _32, _33;
        
        public S2DMatrix()
        {
            _11=0; _12=0; _13=0;
            _21=0; _22=0; _23=0;
            _31=0; _32=0; _33=0;
        }
        
        public DataOutputStream writetostream(DataOutputStream os, S2DMatrix rhs) throws IOException
        {
            os.writeChars("\n");
            os.writeDouble(_11);
            os.writeChars(" ");
            os.writeDouble(_12);
            os.writeChars(" ");
            os.writeDouble(_13);
         
            os.writeChars("\n");
            os.writeDouble(_21);
            os.writeChars(" ");
            os.writeDouble(_22);
            os.writeChars(" ");
            os.writeDouble(_23);
            
            os.writeChars("\n");
            os.writeDouble(_31);
            os.writeChars(" ");
            os.writeDouble(_32);
            os.writeChars(" ");
            os.writeDouble(_33);
            
            return os;
        }
        
        public void copy(S2DMatrix to)
        {
            to._11 = _11;
            to._12 = _12;
            to._13 = _13;
            
            to._21 = _21;
            to._22 = _22;
            to._23 = _23;
            
            to._31 = _31;
            to._32 = _32;
            to._33 = _33;
        }
    }
    
    private S2DMatrix m_Matrix;

    //multiply two matrices together
    //multiplies m_Matrix with mIn
    private void  S2DMatrixMultiply(S2DMatrix mIn)
    {
        S2DMatrix mat_temp = new S2DMatrix();

        //first row
        mat_temp._11 = (m_Matrix._11*mIn._11) + (m_Matrix._12*mIn._21) + (m_Matrix._13*mIn._31);
        mat_temp._12 = (m_Matrix._11*mIn._12) + (m_Matrix._12*mIn._22) + (m_Matrix._13*mIn._32);
        mat_temp._13 = (m_Matrix._11*mIn._13) + (m_Matrix._12*mIn._23) + (m_Matrix._13*mIn._33);

        //second
        mat_temp._21 = (m_Matrix._21*mIn._11) + (m_Matrix._22*mIn._21) + (m_Matrix._23*mIn._31);
        mat_temp._22 = (m_Matrix._21*mIn._12) + (m_Matrix._22*mIn._22) + (m_Matrix._23*mIn._32);
        mat_temp._23 = (m_Matrix._21*mIn._13) + (m_Matrix._22*mIn._23) + (m_Matrix._23*mIn._33);

        //third
        mat_temp._31 = (m_Matrix._31*mIn._11) + (m_Matrix._32*mIn._21) + (m_Matrix._33*mIn._31);
        mat_temp._32 = (m_Matrix._31*mIn._12) + (m_Matrix._32*mIn._22) + (m_Matrix._33*mIn._32);
        mat_temp._33 = (m_Matrix._31*mIn._13) + (m_Matrix._32*mIn._23) + (m_Matrix._33*mIn._33);

        mat_temp.copy(m_Matrix);
    }
    
    public C2DMatrix()
    {
        //initialize the matrix to an identity matrix
        Identity();
    }
    
    //create an identity matrix
    public void Identity()
    {
	m_Matrix._11 = 1; m_Matrix._12 = 0; m_Matrix._13 = 0;
	m_Matrix._21 = 0; m_Matrix._22 = 1; m_Matrix._23 = 0;
	m_Matrix._31 = 0; m_Matrix._32 = 0; m_Matrix._33 = 1;
    }
    
    //create a transformation matrix
    public void Translate(double x, double y)
    {
	S2DMatrix mat = new S2DMatrix();
	
	mat._11 = 1; mat._12 = 0; mat._13 = 0;
	mat._21 = 0; mat._22 = 1; mat._23 = 0;
	mat._31 = x;    mat._32 = y;    mat._33 = 1;
	
	//and multiply
        S2DMatrixMultiply(mat);
    }
    
    //create a scale matrix
    public void Scale(double xScale, double yScale)
    {
	S2DMatrix mat = new S2DMatrix();
	
	mat._11 = xScale; mat._12 = 0; mat._13 = 0;
	mat._21 = 0; mat._22 = yScale; mat._23 = 0;
	mat._31 = 0; mat._32 = 0; mat._33 = 1;
	
	//and multiply
        S2DMatrixMultiply(mat);
    }

    //create a rotation matrix
    public void Rotate(double rotation)
    {
	S2DMatrix mat = new S2DMatrix();

	double Sin = Math.sin(rotation);
	double Cos = Math.cos(rotation);
	
	mat._11 = Cos;  mat._12 = Sin; mat._13 = 0;
	mat._21 = -Sin; mat._22 = Cos; mat._23 = 0;
	mat._31 = 0; mat._32 = 0;mat._33 = 1;
	
	//and multiply
        S2DMatrixMultiply(mat);
    }

    //applies a 2D transformation matrix to a std::vector of SPoints
    //applys a transformation matrix to a std::vector of points
    public void TransformSPoints(Vector<SPoint> vPoint)
    {
        for (int i=0; i<vPoint.size(); ++i)
        {
            double tempX =(m_Matrix._11*vPoint.get(i).x) + (m_Matrix._21*vPoint.get(i).y) + (m_Matrix._31);
            double tempY = (m_Matrix._12*vPoint.get(i).x) + (m_Matrix._22*vPoint.get(i).y) + (m_Matrix._32);
            vPoint.get(i).x = (float) tempX;
            vPoint.get(i).y = (float) tempY;
        }    
    }
}